// Clock1 is a TCP server that periodically writes the time.
package main

import (
	"demo/8.2/ftp"
	"encoding/binary"
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"runtime/debug"
	"strings"
)

func main() {
	listener, err := net.Listen("tcp", "localhost:8000")
	if err != nil {
		log.Fatal(err)
	}

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Print(err) // e.g., connection aborted
			continue
		}
		go handleConn(conn) // handle one connection at a time
	}
}

func handleConn(c net.Conn) {
	defer c.Close()

	for {
		commandBytes, err := ftp.ReadData(c)
		if err != nil {
			ftp.LogError(err)
			continue
		}
		str := string(commandBytes)

		args := strings.Split(str, " ")

		switch args[0] {
		case "get": // 获取服务器上的文件
			getFile(c, args[1:])
		case "send": // 上传文件到服务器上
			sendFile(c, args[1:])
		case "close":
			return
		default: // 演示如此使用，实际这样很危险，不安全
			execCmd(c, str)
		}
	}
}

func getFile(c net.Conn, commands []string) {
	if len(commands) > 1 {
		respError(c, errors.New("暂时只允许获取单个服务器上的文件"))
		return
	}

	fileBytes, err := os.ReadFile(commands[0])
	if err != nil {
		respError(c, err)
		return
	}
	resp(c, fileBytes)
}

func sendFile(c net.Conn, commands []string) {
	if len(commands) > 1 {
		respError(c, errors.New("暂时只允许上传单个文件到服务器"))
		return
	}

	fileBytes, err := ftp.ReadData(c)
	if err != nil {
		respError(c, err)
		return
	}
	err = os.WriteFile(fmt.Sprintf("/home/dwq/code/golang/demo/up/%s", filepath.Base(commands[0])), fileBytes, 0666)
	if err != nil {
		respError(c, err)
		return
	}
}

func execCmd(c net.Conn, commandStr string) {
	retBytes, err := exec.Command("bash", "-c", commandStr).CombinedOutput()
	if err != nil {
		respError(c, err)
		return
	}

	resp(c, retBytes)
}

func resp(c net.Conn, content []byte) {
	err := binary.Write(c, binary.BigEndian, int32(len(content)))
	if err != nil {
		respError(c, err)
	}
	_, err = c.Write(content)
	if err != nil {
		respError(c, err)
	}
}

func respError(c net.Conn, err error) {
	debug.PrintStack()
	log.Printf("err:%v", err)
}
